Skip to content

User/saulg/fuzzer#325

Merged
richiemsft merged 11 commits into
mainfrom
user/saulg/Fuzzer
May 22, 2026
Merged

User/saulg/fuzzer#325
richiemsft merged 11 commits into
mainfrom
user/saulg/Fuzzer

Conversation

@richiemsft

@richiemsft richiemsft commented May 15, 2026

Copy link
Copy Markdown
Contributor

📖 Description

Adds continuous fuzzing infrastructure for MXC's config-parsing surface using cargo-fuzz (libFuzzer) + OneFuzz.

What's included:

  • 3 fuzz targets: config_parser, base64_decode, validator
  • Seed corpus derived from existing test configs and examples
  • Azure Pipeline (Fuzz.Build.yml) with daily cron schedule on main
  • OneFuzzConfig.json with ADO bug routing to Tessera area path
  • Documentation in docs/fuzzing.md and src/fuzz/README.md

Pipeline behavior:

  • trigger: none / pr: none — only runs on daily cron (00:00 UTC)
  • Builds with AddressSanitizer on Windows x64
  • Stages drop directory and submits to OneFuzz

🔍 Validation

  • All 3 fuzz targets run locally on macOS (nightly toolchain) without crashes
  • config_parser: ~959K runs in 11s ✅
  • base64_decode: ~1.3M runs in 11s ✅
  • validator: ~893K runs in 11s ✅
  • YAML validated as syntactically correct
  • OneFuzzConfig paths aligned with pipeline staging layout

✅ Checklist

📋 Issue Type

  • New feature

richiemsft and others added 2 commits May 15, 2026 13:35
Introduces an `mxc_fuzz` crate at `src/fuzz/` with three libFuzzer
targets that cover the attacker-influenced JSON / base64 config surface
consumed by `wxc-exec` and `lxc-exec`:

- `config_parser`: feeds raw JSON into `load_mxc_request`.
- `base64_decode`: same entry point with `is_base64 = true` to cover
  the SDK-supplied wire format end to end.
- `validator`: parses, then runs successful one-shot requests through
  `validate_common`.

The crate is excluded from the parent Cargo workspace so `libfuzzer-sys`
and the nightly-only `-Z sanitizer=address` flag are only pulled in when
fuzzing. Seed corpora are curated one-per-shape from `test_configs/`
(26 / 26 / 11 files). OneFuzz expands the corpus across daily runs.

Local smoke test on Windows x64 with nightly Rust + ASAN: all three
targets compile and run cleanly with no findings against the seed corpus
(~6k-28k exec/s, 81-86 edges of coverage on the parse target).

Platform coverage: targets are pure Rust (`wxc_common`) and are
cross-platform, so the same source compiles on Linux / macOS. We run
them under OneFuzz on Windows only because (a) OneFuzz supports only
Windows, Ubuntu, AzureLinux3, and TKO -- macOS is not a supported
OneFuzz platform, and (b) for these parser targets the bugs are
platform-independent, so a single OS gives full coverage of the
relevant code paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- `src/fuzz/OneFuzzConfig.json`: manifest for the three libFuzzer
  targets. Routing fields (Owners, AssignedTo, NotificationEmail,
  Project, AreaPath, IterationPath) are placeholders pending DRI input;
  they can be filled in without rebuilding any code. Validate with
  `oip.exe validate` before the first submission.
- `.azure-pipelines/templates/Fuzz.Build.Job.yml`: 1ES PT job that
  installs nightly Rust + cargo-fuzz, builds with AddressSanitizer,
  stages the OneFuzz drop directory (per-fuzzer subdir with .exe + ASAN
  runtime DLL + seed corpus), publishes the drop as a pipeline artifact,
  and submits via `onefuzz-task@0`. Submission is skipped on PR runs.
- `.azure-pipelines/Fuzz.Build.yml`: top-level pipeline. `pr: none`,
  `trigger: none`, daily 00:00 UTC cron on `main`. Extends the 1ES
  Unofficial template (no ESRP signing -- the binaries are ASAN-
  instrumented and only ever consumed by OneFuzz).
- `docs/fuzzing.md` and `src/fuzz/README.md`: how to run targets
  locally, minimize the corpus, and triage bugs filed by OneFuzz.

Cargo registry stays pointed at Mxc-Azure-Feed in CI so all crate
sources still come from the internal feed; only the rustc/cargo
binaries come from rustup nightly. A TODO is left to migrate to a
Microsoft-published nightly via msrustup once one is available.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 15, 2026 20:50
Reverts to trigger: none before merge to main; bring-up only.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a fuzzing setup to MXC focused on the attacker-influenced config parsing/validation surface in wxc_common, with local cargo-fuzz harnesses and a scheduled Azure Pipelines job that stages and submits fuzzers to OneFuzz.

Changes:

  • Introduces a standalone mxc_fuzz crate (src/fuzz/) with 3 libFuzzer targets (config_parser, base64_decode, validator) and curated seed corpora.
  • Adds a daily scheduled Azure Pipelines definition + job template to build the fuzzers with AddressSanitizer and submit to OneFuzz.
  • Adds end-user documentation for local and CI fuzzing workflows.

Reviewed changes

Copilot reviewed 74 out of 74 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/fuzz/README.md Local usage docs for cargo-fuzz targets and artifacts/corpus handling.
src/fuzz/OneFuzzConfig.json OneFuzz job manifest describing 3 fuzzing jobs and ADO routing.
src/fuzz/fuzz_targets/validator.rs Fuzz target that parses input and runs validate_common for one-shot requests.
src/fuzz/fuzz_targets/config_parser.rs Fuzz target for load_mxc_request with raw JSON input.
src/fuzz/fuzz_targets/base64_decode.rs Fuzz target for load_mxc_request with base64-encoded input.
src/fuzz/corpus/validator/basic_lpac.json Seed corpus input (validator target).
src/fuzz/corpus/validator/basic_lxc.json Seed corpus input (validator target).
src/fuzz/corpus/validator/basic_permissive.json Seed corpus input (validator target).
src/fuzz/corpus/validator/basic_processcontainer.json Seed corpus input (validator target).
src/fuzz/corpus/validator/containment_process_intent.json Seed corpus input (validator target).
src/fuzz/corpus/validator/hello_world_v050.json Seed corpus input (validator target).
src/fuzz/corpus/validator/hyperlight_fs.json Seed corpus input (validator target).
src/fuzz/corpus/validator/hyperlight_hello.json Seed corpus input (validator target).
src/fuzz/corpus/validator/isolation_session_filesystem.json Seed corpus input (validator target).
src/fuzz/corpus/validator/isolation_session_hello.json Seed corpus input (validator target).
src/fuzz/corpus/validator/isolation_session_state_aware_exec_basic.json Seed corpus input (validator target).
src/fuzz/corpus/validator/isolation_session_state_aware_provision.json Seed corpus input (validator target).
src/fuzz/corpus/validator/isolation_session_state_aware_stop.json Seed corpus input (validator target).
src/fuzz/corpus/validator/lxc_filesystem_test.json Seed corpus input (validator target).
src/fuzz/corpus/validator/microvm_error.json Seed corpus input (validator target).
src/fuzz/corpus/validator/microvm_hello.json Seed corpus input (validator target).
src/fuzz/corpus/validator/microvm_timeout.json Seed corpus input (validator target).
src/fuzz/corpus/validator/network_default_test.json Seed corpus input (validator target).
src/fuzz/corpus/validator/network_firewall_test.json Seed corpus input (validator target).
src/fuzz/corpus/validator/rejected_version_too_old.json Seed corpus input (validator target).
src/fuzz/corpus/validator/windows_sandbox_echo.json Seed corpus input (validator target).
src/fuzz/corpus/validator/windows_sandbox_powershell.json Seed corpus input (validator target).
src/fuzz/corpus/validator/windows_sandbox_timeout.json Seed corpus input (validator target).
src/fuzz/corpus/validator/wslc_custom_registry.json Seed corpus input (validator target).
src/fuzz/corpus/validator/wslc_filesystem.json Seed corpus input (validator target).
src/fuzz/corpus/validator/wslc_python_hello.json Seed corpus input (validator target).
src/fuzz/corpus/config_parser/basic_lpac.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/basic_lxc.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/basic_permissive.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/basic_processcontainer.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/containment_process_intent.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/hello_world_v050.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/hyperlight_fs.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/hyperlight_hello.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/isolation_session_filesystem.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/isolation_session_hello.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/isolation_session_state_aware_exec_basic.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/isolation_session_state_aware_provision.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/isolation_session_state_aware_stop.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/lxc_filesystem_test.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/microvm_error.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/microvm_hello.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/microvm_timeout.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/network_default_test.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/network_firewall_test.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/rejected_version_too_old.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/windows_sandbox_echo.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/windows_sandbox_powershell.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/windows_sandbox_timeout.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/wslc_custom_registry.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/wslc_filesystem.json Seed corpus input (config_parser target).
src/fuzz/corpus/config_parser/wslc_python_hello.json Seed corpus input (config_parser target).
src/fuzz/corpus/base64_decode/basic_lxc.b64.txt Seed corpus input (base64_decode target).
src/fuzz/corpus/base64_decode/basic_processcontainer.b64.txt Seed corpus input (base64_decode target).
src/fuzz/corpus/base64_decode/empty.txt Seed corpus input (base64_decode target).
src/fuzz/corpus/base64_decode/hello_world_v050.b64.txt Seed corpus input (base64_decode target).
src/fuzz/corpus/base64_decode/invalid_chars.txt Seed corpus input (base64_decode target).
src/fuzz/corpus/base64_decode/isolation_session_hello.b64.txt Seed corpus input (base64_decode target).
src/fuzz/corpus/base64_decode/microvm_hello.b64.txt Seed corpus input (base64_decode target).
src/fuzz/corpus/base64_decode/padding_only.txt Seed corpus input (base64_decode target).
src/fuzz/corpus/base64_decode/unpadded.txt Seed corpus input (base64_decode target).
src/fuzz/corpus/base64_decode/valid_hello.txt Seed corpus input (base64_decode target).
src/fuzz/corpus/base64_decode/windows_sandbox_echo.b64.txt Seed corpus input (base64_decode target).
src/fuzz/Cargo.toml Defines mxc_fuzz crate dependencies and fuzz target bins.
src/fuzz/.gitignore Ignores fuzz-specific build outputs, artifacts, and coverage.
src/Cargo.toml Excludes src/fuzz from the Rust workspace.
docs/fuzzing.md End-to-end documentation for fuzzing locally and via the CI pipeline.
.azure-pipelines/templates/Fuzz.Build.Job.yml Pipeline job template to build ASAN fuzzers and stage a OneFuzz drop.
.azure-pipelines/Fuzz.Build.yml Scheduled daily pipeline definition to run the fuzz build + submit stage.

Comment thread .azure-pipelines/templates/Fuzz.Build.Job.yml Outdated
Comment thread src/fuzz/OneFuzzConfig.json
Comment thread src/fuzz/OneFuzzConfig.json
Comment thread src/fuzz/README.md Outdated
Comment thread src/fuzz/README.md Outdated
Comment thread docs/fuzzing.md Outdated
Richie Gomez and others added 3 commits May 18, 2026 11:10
Remove branch-trigger used during bring-up validation. The pipeline
will only run on the daily cron schedule (00:00 UTC on main).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- OneFuzzConfig.json: Update FuzzerExe, JobDependencies, and Seeds
  paths to include target subdirectory prefix (matches pipeline staging
  layout: <target>/<exe>, <target>/corpus)
- OneFuzzConfig.json: Replace TODO placeholders with real ADO routing
  (Project: OS, AreaPath: OS\Windows Client and Services\WinPD\
  AgOS-Agentic Platform\Agent Runtime\Tessera)
- README.md: Fix relative paths (already cd'd into src/fuzz)
- docs/fuzzing.md: Fix artifact paths to be relative to src/fuzz

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@richiemsft richiemsft marked this pull request as ready for review May 18, 2026 18:26
Comment thread .azure-pipelines/Fuzz.Build.yml Outdated
Comment thread .azure-pipelines/Fuzz.Build.yml
Comment thread src/fuzz/fuzz_targets/validator.rs
Comment thread src/fuzz/OneFuzzConfig.json
Comment on lines +7 to +12
# Nightly Rust toolchain: cargo-fuzz requires `-Z sanitizer=address`, which
# only nightly accepts. The Mxc-Azure-Feed (`ms-prod-*`) toolchains are
# stable-only today, so we install nightly via `rustup-init` here.
# TODO(SFI): switch to a Microsoft-published nightly via msrustup once one
# is available in Mxc-Azure-Feed; until then keep cargo registry pointed at
# Mxc-Azure-Feed so all *crate* sources still come from the internal feed.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Is this something I need to add? I can check and get back to you

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unsure, haven't been able to test the azure side since in order to generate the pipeline the code has to be check in. I couldn't reference a non checked in file.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all good, lets check it in so you can try it out. There is a way to do it without having to check it in though if I recall but it's ok lets get it in.

Richie Gomez and others added 2 commits May 22, 2026 09:47
- Remove bring-up branch comment from Fuzz.Build.yml (bbonaby)
- Use test_configs/ as seed corpus for config_parser and validator targets
  instead of maintaining duplicated files in src/fuzz/corpus/ (bbonaby)
- Keep src/fuzz/corpus/base64_decode/ for pre-encoded seeds
- Update pipeline staging to copy from test_configs/*.json
- Enhance validator fuzz target to call runner-specific validate_runner
  based on containment backend (bbonaby). NanVix always available;
  Hyperlight and IsolationSession behind opt-in features.
- Build validator target with --features hyperlight,isolation_session in CI
- Update README and docs/fuzzing.md to reflect new corpus source

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The CodexRequest field is named containment, not containment_backend. The fuzz target was failing to build with E0609. Verified locally by running the validator target for 30s under cargo-fuzz (485k runs, no findings).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread src/fuzz/README.md
@@ -0,0 +1,55 @@
# mxc_fuzz

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Might be worth it for us to have a table at the bottom with what each base64_decode relates to since they won't be human readable

Comment on lines +7 to +12
# Nightly Rust toolchain: cargo-fuzz requires `-Z sanitizer=address`, which
# only nightly accepts. The Mxc-Azure-Feed (`ms-prod-*`) toolchains are
# stable-only today, so we install nightly via `rustup-init` here.
# TODO(SFI): switch to a Microsoft-published nightly via msrustup once one
# is available in Mxc-Azure-Feed; until then keep cargo registry pointed at
# Mxc-Azure-Feed so all *crate* sources still come from the internal feed.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all good, lets check it in so you can try it out. There is a way to do it without having to check it in though if I recall but it's ok lets get it in.

@richiemsft richiemsft merged commit cf9721d into main May 22, 2026
18 checks passed
@richiemsft richiemsft deleted the user/saulg/Fuzzer branch May 22, 2026 22:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants